gin,今天再喝一杯吧。
因為我們的目標是網頁伺服器,果不其然的要從網頁開始講起。
HTTP Method 分成了八種GET、POST、DELETE、PUT、HEAD、TRACE、CONNECT、OPTIONS,但在這我們只會簡介常用的GET跟POST。
GET:參數都放在網址裡,很不安全(要是參數是登入時的帳號、密碼,就會容易外洩),但方便開發的時候測試。POST:參數不在網址裡,比較安全的作法。Json (JavaScript Object Notation) 是一種資料格式,由各種 陣列(Array)以及鍵值(Key-Value)所組成的結構話格式。
[]是陣列形式,裡面可以放各種物件
{}是鍵值形式,裡面可以放各種物件
兩種形式可以交錯使用,你中有我我中有你
以下使用gin不同的兩種方式(Context.Data,Context.JSON)來達成 返回json資料格式的效果:
func main() {
router := gin.Default()
router.GET("/json", returnJson)
router.GET("/json2", returnJson2)
router.Run(":80")
}
func returnJson(c *gin.Context) {
m := map[string]string{"status": "ok"}
j, _ := json.Marshal(m)
c.Data(http.StatusOK, "application/json", j)
}
func returnJson2(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"狀態": "ok",
})
}

(在這推薦安裝Chrome擴充套件 JSON Viewer Pro
或其他款可以在瀏覽器上方便看json檔案的套件,畫面看起來更舒適)

另外,可以透過Chrome開發者工具 看到Content-Type為剛剛所設定的application/json

可以直接在struct中加入json tag,讓gin返回json格式的時候自動對應轉換。
(當然也有支援xml等格式,甚至可以自訂格式)
func returnJson3(c *gin.Context) {
type Result struct {
Status string `json:"status"`
Message string `json:"message"`
}
var result = Result{
Status: "OK",
Message: "This is Json",
}
c.JSON(http.StatusOK, result)
}
記得 struct中的 Status、Message要字首大寫,要對外暴露給gin套件取用
GET Method 是以網址帶參數的方式進行參數傳遞,可分成以下兩種:
查詢參數(Query Params)
路徑參數(Path Params)
127.0.0.1?
user=id
參數名稱為user
其中的id就是使用者的ID。127.0.0.1?user=Jack
為什麼叫作查詢參數、或稱作Query String呢?
因為他使用?問號來 Query參數
能以這方法夾帶表單參數(HTML Form),但傳遞表單時使用POST方法更為安全。
func main() {
router := gin.Default()
router.GET("/para1", para1)
router.Run(":80")
}
func para1(c *gin.Context) {
// input := c.DefaultQuery("input", "使用者沒有任何輸入。") // 使用者沒有輸入參數時 可設定預設值
input := c.Query("input")
msg := []byte("您輸入的文字為: \n" + input) // 純文字(text/plain)中的換行是\n,網頁格式(html)中的換行才是<br />
c.Data(http.StatusOK, "text/plain; charset=utf-8;", msg) // 如果沒有指定文字編碼、拿掉`charset=utf-8;`的話,中文會變亂碼。
}
成功執行的話,點開後會出現以下結果:
http://127.0.0.1/para1?input=%E5%93%88%E5%93%88%E6%98%AF%E6%88%91%E5%95%A6

路徑即是參數,能以這種方式夾帶參數:
127.0.0.1/
user/id
其中的user是參數名稱,可代表使用者頁面,
id就是使用者的ID。127.0.0.1/user/Jack
func main() {
router := gin.Default()
router.GET("/para2/:input", para2)
router.Run(":80")
}
func para2(c *gin.Context) {
msg := c.Param("input")
c.String(http.StatusOK, "您輸入的文字為: \n%s", msg) // 也可使用 `c.String`返回。第二個參數為組合樣式format
// c.String(http.StatusOK, msg) // 如果沒有組合樣式,可直接輸入字串
}
成功執行的話,點開後會出現以下結果:
http://127.0.0.1/para2/%E5%93%88%E5%93%88%E6%98%AF%E6%88%91%E5%95%A6

post有寄信、發布訊息的意思
func main() {
router := gin.Default()
router.RedirectFixedPath = true
router.POST("/post", post)
router.Run(":80")
}
func post(c *gin.Context) {
//msg := c.PostForm("input")
msg := c.DefaultPostForm("input", "表單沒有input。") // 沒有輸入參數時 可設定預設值
c.String(http.StatusOK, "您輸入的文字為: \n%s", msg)
}
由於POST Method參數都隱藏起來了,並非像GET在網址列填入參數就能達到目的,
開瀏覽器難以測試。在這邊我們會使用到Postman工具來做測試。
測試時選擇POST方法

選擇Body,格式選擇form-data,
並且填入表單的Key、Value

router.Any是任何方法都能夠 handle 的。
Any registers a route that matches all the HTTP methods.
包含 GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE.
func main() {
router := gin.Default()
router.Any("/any", any)
router.Run(":80")
}
func any(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
})
}
gin預設是**大小寫敏感(case sensitivity)**的,只要對應的URI字符大小寫不同即視為不同,
這在一些使用情境下非常的不便。
加上這行 重導向正確的URI,讓大小寫通吃。
router.RedirectFixedPath = true